/**
 * 格式化时间为指定样式
 * @param {(Object|string|number)} time 时间对象/字符串/时间毫秒
 * @param {string} cFormat 格式化样式格式
 * @returns {string | null}
 */
export function parseTime(time, cFormat) {
  // arguments：实参伪数组，只存在于函数内部使用
  // ||后边为何这么写？可能time传入的是一个undefined/null/...
  if (arguments.length === 0 || !time) { // 没有传参，或者传参为空
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date // 保存日期对象
  if (typeof time === 'object') {
    date = time
  } else {
    // 时间是字符串，转换为数字形式
    if ((typeof time === 'string')) {
      if ((/^[0-9]+$/.test(time))) { // 是否都是0-9数字组成
        // support "1548221490638"
        // 把毫秒字符串格式化为数字
        time = parseInt(time)
      } else {
        // support safari 支持IOS内置的浏览器
        // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
        // 如果时间字符串是 1-3-2023 形式的
        // 字符串.replace() 替换方法，可以将参数1匹配的，直接换成参数2，并返回新的字符串
        // g 全局匹配们可以匹配多次，不然只能替换一个-
        // m 多行匹配，如果字符串里包含多行回车，也可以匹配到
        time = time.replace(new RegExp(/-/gm), '/')
        // 处理后样式：1/3/2023
      }
    }

    // 如果是数字，并且长度是10位（传进来的是秒），但是new Date()里有求传入的是毫秒
    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000// 秒转成毫秒
    }
    // 转为时间对象
    date = new Date(time)
  }

  const formatObj = {
    y: date.getFullYear(), // 英文字符：日期对象时间值
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }

  // 要把占位符进行替换，使用replace()方法
  // 正则：先匹配到左右两侧必须是{}，接着匹配{}中间是([ymdhisa])任意一个一次到多次
  // replace()参数2，可以是直接替换的值
  const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
    // result:匹配到的字符串({y},{m}......)
    // key: 匹配到的()正则里的(y,m....)

    // 获取对应位置的值
    const value = formatObj[key]
    // 如果最后有一个a，用0-6作为下标，换出星期几
    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
    return value.toString().padStart(2, '0') // 字符串.padStart(a,b)   字符串长度不够a位，在前边使用b补齐
  })
  return time_str
}

/**
 * 两天内的会返回相距时间，两天之后的返回传入时间
 * @param {number} time  传入时间戳
 * @param {string} option 格式化的占位符 有y,m....
 * @returns {string}
 */
export function formatTime(time, option) {
  if (('' + time).length === 10) { // 传入秒
    time = parseInt(time) * 1000 // 变成毫秒
  } else {
    time = +time // 转成数字
  }
  const d = new Date(time) // 时间戳变成日期对象
  const now = Date.now() // 当前的时间戳

  const diff = (now - d) / 1000 // 可以用时间戳-日期对象(返回时间差值)
  // diff当前时间和传入目标时间，相差多少秒

  if (diff < 30) {
    return '刚刚'
  } else if (diff < 3600) {
    // 小于一小时
    return Math.ceil(diff / 60) + '分钟前'
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小时前'
  } else if (diff < 3600 * 24 * 2) {
    return '1天前'
  }

  // 超过一天，如果传入占位符，就按照上方的格式传递
  if (option) {
    return parseTime(time, option)
  } else {
    // 如果没有传入占位符，就按照下方样式展示
    return (
      d.getMonth() +
      1 +
      '月' +
      d.getDate() +
      '日' +
      d.getHours() +
      '时' +
      d.getMinutes() +
      '分'
    )
  }
}

/**
 * 将url地址中的参数字符串转换为对象形式
 * @param {string} url
 * @returns {Object} 返回一个参数字符串的对象
 */
export function param2Obj(url) {
  // decodeURIComponent   内置的，可以将url编码转换为原来的样子

  // url.split('?')[1]  获取url中的参数字符串，
  // url.split('?')[1]).replace(/\+/g, ' ')  将参数字符串中的 + 换成   空格
  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') // search 获取查询字符串参数

  // 如果没有参数字符串
  if (!search) {
    return {}
  }

  // 如果有参数字符串
  const obj = {}
  // 将参数字符串按 & 分割，获取每一个键值对
  const searchArr = search.split('&')
  // 对获取的键值对遍历，v表示数组中的每一项
  searchArr.forEach(v => {
    // 查询每个键值对的 = 位置
    const index = v.indexOf('=')
    // 如果 = 存在
    if (index !== -1) {
      // substring() 截取字符串，含前不含后
      const name = v.substring(0, index) // 返回键名
      const val = v.substring(index + 1, v.length) // 返回键值
      obj[name] = val // 将获取的参数以键值对的形式存放在 obj 中
    }
  })
  return obj // 返回obj
}
